import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.util.Iterator;

import com.hp.hpl.jena.ontology.*;
import com.hp.hpl.jena.rdf.model.Container;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.RDFList;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Seq;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.vocabulary.OWL;

public class JenaTester {

	static class ClassTemplate extends JenaTester {
		OntClass Subject = null;
		RDFList SEQ=null;
		OntClass CompClass = null;

		public void PrintList()
		{
			System.out.println(SEQ.asJavaList().toString());
		}

		public OntClass getSubject(){
			return this.Subject;
		}

		class UnionTemplate extends ClassTemplate {
			public UnionTemplate(OntClass n){
				Subject = n;
				UnionClass UC = Subject.asUnionClass();
				SEQ = UC.getOperands();
			}
			public RDFList getSEQ(){
				return this.SEQ;
			}
		}

		class ComplementTemplate extends ClassTemplate {
			public ComplementTemplate(OntClass n){
				Subject = n;
				ComplementClass UC = Subject.asComplementClass();
				CompClass = UC.getOperand();
			}

			public OntClass getSEQ(){
				return this.CompClass;
			}
		}
		/*		class DisjointTemplate extends ClassTemplate {
			public DisjointTemplate(OntClass n){
				Subject = n;
				DisjointWith UC = Subject.asDisjointClass();
				SEQ = UC.getOperands();
			}
		}*/
		class IntersectionTemplate extends ClassTemplate {
			public IntersectionTemplate(OntClass n){
				Subject = n;
				IntersectionClass UC = Subject.asIntersectionClass();
				SEQ = UC.getOperands();
			}
			public RDFList getSEQ(){
				return this.SEQ;
			}
		}
	}

	public static class RstrTemplate extends JenaTester {
		int AllValueType = 0;
		int SomeValueType = 1;
		int MinCardinality = 0;
		int ExactCardinality = 1;
		int MaxCardinality = 2;

		OntProperty prop=null;
		OntClass objclass=null;
		Literal hasvalue=null;
		Resource R = null;
		int CardinalityValue = 0 ;

		public OntProperty getProperty(){
			return this.prop;
		};

		public OntClass getObjectClass(){
			return this.objclass;
		}

		class CCardinalityTemplate extends RstrTemplate {
			int CardinalityType = -1;			

			public CCardinalityTemplate(int cardtype, Restriction r){
				CardinalityType = cardtype;
				if(CardinalityType == 0){
					MinCardinalityRestriction MinCard =  r.asMinCardinalityRestriction();
					prop = MinCard.getOnProperty();
					CardinalityValue = MinCard.getMinCardinality();
					objclass = (OntClass)MinCard.getOnProperty().getRange().asClass();
				}
				if(CardinalityType == 1){
					CardinalityRestriction Card = r.asCardinalityRestriction();
					prop = Card.getOnProperty();
					CardinalityValue = Card.getCardinality();
					R = Card.getOnProperty().getRange();
					objclass = (OntClass)Card.getOnProperty().getRange().asClass();
				}
				if(CardinalityType == 2){
					MaxCardinalityRestriction MaxCard = r.asMaxCardinalityRestriction();
					prop = MaxCard.getOnProperty();
					CardinalityValue = MaxCard.getMaxCardinality();
					objclass = (OntClass)MaxCard.getOnProperty().getRange().asClass();
				}				
			}

			public int getCardinalityValue(){
				return this.CardinalityValue;
			}

			public int GetCardinalityType(){
				return this.CardinalityType;
			}

		}
		class LCardinalityTemplate extends RstrTemplate {
			int CardinalityType = -1;			

			public LCardinalityTemplate(int cardtype, Restriction r){
				CardinalityType = cardtype;
				if(CardinalityType == 0){
					MinCardinalityRestriction MinCard =  r.asMinCardinalityRestriction();
					prop = MinCard.getOnProperty();
					CardinalityValue = MinCard.getMinCardinality();
				}
				if(CardinalityType == 1){
					CardinalityRestriction Card = r.asCardinalityRestriction();
					prop = Card.getOnProperty();
					CardinalityValue = Card.getCardinality();
				}
				if(CardinalityType == 2){
					MaxCardinalityRestriction MaxCard = r.asMaxCardinalityRestriction();
					prop = MaxCard.getOnProperty();
					CardinalityValue = MaxCard.getMaxCardinality();
				}				
			}

			public int getCardinalityValue(){
				return this.CardinalityValue;
			}

			public int GetCardinalityType(){
				return this.CardinalityType;
			}
		}
		class HasValueTemplate extends RstrTemplate {
			//			Ontliteral literal;
			//			getLiteral()
			public HasValueTemplate(OntClass AnonRestr){
				Restriction r = (Restriction) AnonRestr;
				HasValueRestriction Has = r.asHasValueRestriction();
				prop = Has.getOnProperty();
				hasvalue = (Literal)Has.getHasValue();
			}
		}
		class ValueTemplate extends RstrTemplate {

			int ValueType = -1;

			public ValueTemplate(int valuetype, Restriction r){
				ValueType = valuetype;
				if (ValueType == AllValueType)	{
					AllValuesFromRestriction All = r.asAllValuesFromRestriction(); 
					prop = All.getOnProperty();
					objclass = (OntClass)All.getAllValuesFrom();
				}
				else if (ValueType == SomeValueType)	{
					SomeValuesFromRestriction Some = r.asSomeValuesFromRestriction();
					prop = Some.getOnProperty();
					objclass = (OntClass)Some.getSomeValuesFrom();
				}
				else
					System.out.println("Can not get ValueType");
			}

			public int getValueType(){
				return ValueType;
			}
		}
	}
	public static void oldDemo(File onto1) throws IOException{
		OntModel m = ModelFactory.createOntologyModel();
		FileInputStream in = new FileInputStream(onto1);
		BufferedInputStream bin = new BufferedInputStream(in);
		m.read(bin, null, "RDF/XML");
		String outfile = "/Users/tejascha/Documents/Data/BenchMark/AnonList_"+onto1.toString().substring(onto1.toString().lastIndexOf("/")+1,onto1.toString().lastIndexOf("."))+".txt";
		FileWriter out = new FileWriter(outfile);
		BufferedWriter write = new BufferedWriter(out);
		int start = 0;
		String URI = "http://www.semanticweb.org/ontologies/2011/5/Ontology1308147369708.owl#";
		String buffer = m.listClasses().toList().toString().replace(",", "\n").replace(URI,"");
		System.out.println("_______________________________________________________");
		//        System.out.println(buffer);
		int k = m.listClasses().toList().size();
		Iterator <Restriction>side0 = m.listRestrictions();
		Iterator <OntClass>side1 = m.listClasses();
		int i = m.listRestrictions().toList().size();
		int j = 0;
		while(side0.hasNext()){
			j++;
			Restriction r = (Restriction) side0.next();
			OntProperty p = r.getOnProperty();

			System.out.println(			"Iter:" + j +"/" + i  
					+"\nRESTONCLASS:\t "+ r.listSubClasses().toList().toString().replace("]","").replace("[","").replace(",","\n\t\t")//.substring( r.listSubClasses().toString().indexOf("#")+1,  r.listSubClasses().toString().length())
					//		+"\nONPROP: "+ r.getOnProperty().toString().substring( r.getOnProperty().toString().indexOf("#")+1,  r.getOnProperty().toString().length())
					//+"\nRANGE: " + p.listRange().toList().toString().replace(",","\n\t\t")
					);
			write.write(			"\nIter:" + j +"/" + i  
					+"\nRESTONCLASS:\t "+ r.listSubClasses().toList().toString().replace("]","").replace("[","").replace(",","\n\t\t")//.substring( r.listSubClasses().toString().indexOf("#")+1,  r.listSubClasses().toString().length())
					//		+"\nONPROP: "+ r.getOnProperty().toString().substring( r.getOnProperty().toString().indexOf("#")+1,  r.getOnProperty().toString().length())
					//+"\nRANGE: " + p.listRange().toList().toString().replace(",","\n\t\t")
					);
			//   		if(!p.isDataRange() || !p.isDatatypeProperty())
			// 		{
			//		System.out.println("\nONCLASS: "+p.listRange().toList().toString().toString().substring( p.getRange().toString().indexOf("#")+1,  p.getRange().toString().length()));
			//		}
			AllValuesFromRestriction ar = null; 
			if (r.isAllValuesFromRestriction()){
				ar = r.asAllValuesFromRestriction();
				System.out.println(""
						+  "ONPROP:\t \t "+ ar.getOnProperty().toString()//.substring( ar.getOnProperty().toString().indexOf("#")+1,  ar.getOnProperty().toString().length())
						+  "\nALLVALUE:\t "+ar.getAllValuesFrom().toString()//.substring(ar.getAllValuesFrom().toString().indexOf("#")+1, ar.getAllValuesFrom().toString().length())
						);
				write.write("\n"
						+  "ONPROP:\t \t "+ ar.getOnProperty().toString()//.substring( ar.getOnProperty().toString().indexOf("#")+1,  ar.getOnProperty().toString().length())
						+  "\nALLVALUE:\t "+ar.getAllValuesFrom().toString()//.substring(ar.getAllValuesFrom().toString().indexOf("#")+1, ar.getAllValuesFrom().toString().length())
						);
			}
			HasValueRestriction hr = null;
			if (r.isHasValueRestriction()){
				hr = r.asHasValueRestriction();
				System.out.println(""
						+  "ONPROP: \t\t "+ hr.getOnProperty().toString()//.substring( hr.getOnProperty().toString().indexOf("#")+1,  hr.getOnProperty().toString().length())
						+  "\nHASVALUE:\t "+ hr.getHasValue().toString()//.substring(hr.getHasValue().toString().indexOf("#")+1, hr.getHasValue().toString().length())
						);
				write.write("\n"
						+  "ONPROP: \t\t "+ hr.getOnProperty().toString()//.substring( hr.getOnProperty().toString().indexOf("#")+1,  hr.getOnProperty().toString().length())
						+  "\nHASVALUE:\t "+ hr.getHasValue().toString()//.substring(hr.getHasValue().toString().indexOf("#")+1, hr.getHasValue().toString().length())
						);
			}
			SomeValuesFromRestriction sr = null;
			if (r.isSomeValuesFromRestriction()){
				sr = r.asSomeValuesFromRestriction();
				System.out.println(""
						+  "ONPROP:\t \t "+ sr.getOnProperty().toString()//.substring( sr.getOnProperty().toString().indexOf("#")+1,  sr.getOnProperty().toString().length())
						+  "\nSOMEVALUE:\t "+ sr.getSomeValuesFrom().toString()//.substring(sr.getSomeValuesFrom().toString().indexOf("#")+1, sr.getSomeValuesFrom().toString().length())
						);
				write.write("\n"
						+  "ONPROP:\t \t "+ sr.getOnProperty().toString()//.substring( sr.getOnProperty().toString().indexOf("#")+1,  sr.getOnProperty().toString().length())
						+  "\nSOMEVALUE:\t "+ sr.getSomeValuesFrom().toString()//.substring(sr.getSomeValuesFrom().toString().indexOf("#")+1, sr.getSomeValuesFrom().toString().length())
						);
			}
			//OntProperty onclass = m.getOntProperty("http://www.w3.org/2002/07/owl#");
			CardinalityRestriction cr = null;
			if(r.isCardinalityRestriction()){
				cr = r.asCardinalityRestriction();
				System.out.println(""
						+  "ONPROP: \t "+ cr.getOnProperty().toString()
						+  "\nCARDINALITY:\t "+cr.getCardinality()
						+  "\nRANGE:\t\t "+cr.getOnProperty().getRange()
						);
				write.write("\n"
						+  "ONPROP: \t "+ cr.getOnProperty().toString()
						+  "\nCARDINALITY:\t "+cr.getCardinality()
						+  "\nRANGE:\t\t "+cr.getOnProperty().getRange()
						);
			}
			MinCardinalityRestriction micr = null;
			if(r.isMinCardinalityRestriction()){
				micr = r.asMinCardinalityRestriction();
				System.out.println(""
						+  "ONPROP: \t "+ micr.getOnProperty().toString()
						+  "\nMINCARD:\t "+ micr.getMinCardinality()
						+  "\nRANGE:\t\t "+micr.getOnProperty().getRange()
						);
				write.write("\n"
						+  "ONPROP: \t "+ micr.getOnProperty().toString()
						+  "\nMINCARD:\t "+ micr.getMinCardinality()
						+  "\nRANGE:\t\t "+micr.getOnProperty().getRange()
						);
			}
			MaxCardinalityRestriction macr = null;
			if(r.isMaxCardinalityRestriction()){
				macr = r.asMaxCardinalityRestriction();
				System.out.println(""
						+  "ONPROP: \t "+ macr.getOnProperty().toString()
						+  "\nMAXCARD:\t "+ macr.getMaxCardinality()
						+  "\nRANGE:\t\t "+macr.getOnProperty().getRange()
						);
				write.write("\n"
						+  "ONPROP: \t "+ macr.getOnProperty().toString()
						+  "\nMAXCARD:\t "+ macr.getMaxCardinality()
						+  "\nRANGE:\t\t "+macr.getOnProperty().getRange()
						);
			}
			System.out.println("_________________________________________________________________");
			write.write("\n_________________________________________________________________");
			write.flush();
		}
		write.flush();
		while(side1.hasNext()){
			OntClass O = (OntClass) side1.next();
			if(O.isAnon()){
				if(O.isUnionClass()){
					UnionClass O2 = O.asUnionClass();

					System.out.println(""
							+ "\nClass Name: "+O
							+ "\n Is UNION CLASS"
							);
					write.write("\n"
							+ "\nClass Name: "+O
							+ "\n Is UNION CLASS\n"
							);
					Iterator <OntClass> Unionof = O2.listOperands();
					while(Unionof.hasNext()){
						System.out.println(Unionof.next());
					}
					Unionof = O2.listOperands();
					while(Unionof.hasNext()){
						write.write(Unionof.next().toString()+"\n");
					}
					write.flush();
				}
				if(O.isIntersectionClass()){
					IntersectionClass O2 = O.asIntersectionClass();

					System.out.println(""
							+ "\nClass Name: "+O
							+ "\n Is INTERSECTION CLASS"
							);
					write.write("\n"
							+ "\nClass Name: "+O
							+ "\n Is INTERSECTION CLASS\n"
							);
					Iterator <OntClass> intersectionOf = O2.listOperands();
					while(intersectionOf.hasNext()){
						System.out.println(intersectionOf.next());
					}
					intersectionOf = O2.listOperands();
					while(intersectionOf.hasNext()){
						write.write(intersectionOf.next().toString()+"\n");
					}
					write.flush();
					//  			SEQ1.add((RDFNode) O2);
				}
				if(O.isComplementClass()){
					ComplementClass O2 = O.asComplementClass();

					System.out.println(""
							+ "\nClass Name: "+O
							+ "\n Is COMPLEMENT CLASS"
							);
					write.write("\n"
							+ "\nClass Name: "+O
							+ "\n Is COMPLEMENT CLASS\n"
							);
					Iterator <OntClass> Complementof = O2.listOperands();
					RDFList SEQ1= null;
					while(Complementof.hasNext()){
						System.out.println(Complementof.next());
					}
					Complementof = O2.listOperands();
					while(Complementof.hasNext()){
						write.write(Complementof.next().toString()+"\n");
					}
					write.flush();
					//  			SEQ1.add((RDFNode) O2);
				}

			}


		}
	}

	public static void getStats(File onto) throws IOException{

		OntModel m = ModelFactory.createOntologyModel();
		FileInputStream in = new FileInputStream(onto);
		BufferedInputStream bin = new BufferedInputStream(in);
		m.read(bin, null, "RDF/XML");
		//String outfile = "/Users/tejascha/Documents/Data/AnonStats.txt";
		File outfile = new File("/Users/tejascha/Documents/Data/AnonStats.txt");
		FileWriter out = new FileWriter(outfile,true);
		BufferedWriter write = new BufferedWriter(out);
		int k = m.listClasses().toList().size();
		Iterator <Restriction>side0 = m.listRestrictions();
		Iterator <OntClass>side1 = m.listClasses();
		int i = m.listRestrictions().toList().size();
		String filename = onto.toString().substring(onto.toString().lastIndexOf("/")+1,onto.toString().lastIndexOf("."));
		int TotalClasses = k;
		int TotalRestrictions  = i;
		int TotalAnons = 0;
		int MinCardinality = 0;
		int MaxCardinality = 0;
		int Cardinality = 0;
		int AllValue = 0;
		int SomeValue = 0;
		int HasValue = 0;
		while(side0.hasNext()){
			Restriction r = (Restriction) side0.next();
			if (r.isAllValuesFromRestriction()){
				AllValue++;
			}
			if (r.isHasValueRestriction()){
				HasValue++;
			}
			if (r.isSomeValuesFromRestriction()){
				SomeValue++;
			}
			if(r.isCardinalityRestriction()){
				Cardinality++;
			}
			if(r.isMinCardinalityRestriction()){
				MinCardinality++;
			}
			if(r.isMaxCardinalityRestriction()){
				MaxCardinality++;
			}
		}
		int BooleanExp = 0;
		int UnionExp = 0;
		int IntersectionExp = 0;
		int ComplementExp = 0;
		while(side1.hasNext()){
			OntClass O = (OntClass) side1.next();
			if(O.isAnon()){
				if(O.isUnionClass()){
					BooleanExp++;
					UnionExp++;
				}
				if(O.isIntersectionClass()){
					BooleanExp++;
					IntersectionExp++;
				}
				if(O.isComplementClass()){
					BooleanExp++;
					ComplementExp++;
				}
			}
		}
	/*	System.out.println("\nTotal Classes : "+TotalClasses
				+"\nTotal Anonymous Classes : "+TotalAnons
				+"\nTotal Restrictions : "+TotalRestrictions
				+"\nCardinality Restrictions : "+Cardinality
				+"\nMinimum Cardinality : "+MinCardinality
				+"\nMaximum Cardinality : "+MaxCardinality
				+"\nAll Values From : "+AllValue
				+"\nSome Values From : "+SomeValue
				+"\nHas Value : "+HasValue
				+"\nTotal Boolean Exp : "+BooleanExp
				+"\nUnion Expression : "+UnionExp
				+"\nIntersection Expression: "+IntersectionExp
				+"\nComeplement Expression: "+ComplementExp
				);*/
		write.write(filename
				+","+TotalClasses
				+","+TotalAnons
				+","+TotalRestrictions
				+","+BooleanExp
				+","+Cardinality
				+","+MinCardinality
				+","+MaxCardinality
				+","+AllValue
				+","+SomeValue
				+","+HasValue
				+","+UnionExp
				+","+IntersectionExp
				+","+ComplementExp
				);
		write.write("\n");
		write.close();

	}

	public static void getStatsFromDir(String path) throws IOException{
		File dir = new File(path);
		File files[] = dir.listFiles();
		for (int i = 0; i<files.length;i++)
		{	String file = files[i].toString();
			System.out.println(file);
			if(file.contains(".rdf") || file.contains(".owl"))
			{
			File onto = files[i];
			System.out.println(onto);
			getStats(onto);
			}
		}
	}
	public static void Demo(File onto1) throws FileNotFoundException{

		OntModel m = ModelFactory.createOntologyModel();
		FileInputStream in = new FileInputStream(onto1);
		BufferedInputStream bin = new BufferedInputStream(in);
		m.read(bin, null, "RDF/XML");

		Iterator <Restriction> AnonRestrs = m.listRestrictions();

		while(AnonRestrs.hasNext()){
			Restriction r = AnonRestrs.next();
			RstrTemplate rt = new RstrTemplate();
			if (r.isCardinalityRestriction())	{
				if(r.getOnProperty().getRange()==null){
					RstrTemplate.LCardinalityTemplate c = rt.new LCardinalityTemplate(1, r);
					System.out.println("LCardinality:");
					System.out.println("\t "+r.listSubClasses().toList().toString().replace("]","").replace("[","").replace(",","\n\t"));
					System.out.println(c.getProperty());
					System.out.println(c.getCardinalityValue());
				}
				else{
					RstrTemplate.CCardinalityTemplate c = rt.new CCardinalityTemplate(1, r);
					System.out.println("CCardinality:");
					System.out.println("\t "+r.listSubClasses().toList().toString().replace("]","").replace("[","").replace(",","\n\t"));
					System.out.println(c.getObjectClass());
					System.out.println(c.getProperty());
					System.out.println(c.getCardinalityValue());			
				}
			}
			if (r.isAllValuesFromRestriction())	{

				RstrTemplate.ValueTemplate c = rt.new ValueTemplate(0, r);
				System.out.println("AllValuesFrom:");
				System.out.println("\t "+r.listSubClasses().toList().toString().replace("]","").replace("[","").replace(",","\n\t"));
				System.out.println(c.getProperty());
				System.out.println(c.getObjectClass());
			}
		}

		Iterator <OntClass> AnonClass = m.listUnionClasses();
		while(AnonClass.hasNext()){
			OntClass O = AnonClass.next();
			ClassTemplate ct = new ClassTemplate();
			ClassTemplate.UnionTemplate U = ct.new UnionTemplate(O);
			System.out.print("UnionOf: ");
			System.out.println(U.getSubject());
			System.out.println("\t "+U.getSEQ().asJavaList().toString().replace("]","").replace("[","").replace(",","\n\t"));
		}
		Iterator <OntClass> AnonClass1 = m.listIntersectionClasses();
		while(AnonClass1.hasNext()){
			OntClass O = AnonClass1.next();
			ClassTemplate ct = new ClassTemplate();
			ClassTemplate.IntersectionTemplate U = ct.new IntersectionTemplate(O);
			System.out.print("IntersectionOf: ");
			System.out.println(U.getSubject());
			System.out.println("\t "+U.getSEQ().asJavaList().toString().replace("]","").replace("[","").replace(",","\n\t"));
		}
		Iterator <OntClass> AnonClass2 = m.listComplementClasses();
		while(AnonClass2.hasNext()){
			OntClass O = AnonClass2.next();
			ClassTemplate ct = new ClassTemplate();
			ClassTemplate.ComplementTemplate U = ct.new ComplementTemplate(O);
			System.out.print("ComplementOf: ");
			System.out.println(U.getSubject());
			System.out.println("\t "+U.getSEQ().toString());
		}
	}

	public static void main(String[] args) throws IOException {
		//		File onto1 = new File("/Users/tejascha/Documents/Data/BenchMark/OAEI/101.rdf");//		
		//		File onto1 = new File("/Users/tejascha/Documents/Data/BenchMark/OAEI/303.rdf");
		//		File onto1 = new File("/Users/tejascha/Documents/Data/BenchMark/OAEI/ekaw.owl");
		//		File onto1 = new File("/Users/tejascha/Documents/Data/BenchMark/OAEI/edas.owl");
		//		File onto1 = new File("/Users/tejascha/Documents/Data/BenchMark/OAEI/iasted.owl");
		//		File onto1 = new File("/Users/tejascha/Documents/Data/BenchMark/AnimalFood/Animal.rdf");
		//		File onto1 = new File("/Users/tejascha/Documents/Data/BenchMark/AnimalFood/People.rdf");
		//		File onto1 = new File("/Users/tejascha/Documents/Data/BenchMark/Shapes/Objects.rdf");
		//		File onto1 = new File("/Users/tejascha/Documents/Data/BenchMark/Shapes/Shapes.rdf");
		File onto1 = new File("/Users/tejascha/Downloads/Bench/MICRO.owl");
		String path = "/Users/tejascha/Documents/Data/OAEI";
		//oldDemo(onto1);
		getStatsFromDir(path);
		//	Demo(onto2);
		//		Demo(onto1);		
	}
}
